package cn.luke.basic.services;

import cn.dev33.satoken.stp.StpUtil;
import cn.luke.basic.entity.DtoDic;
import cn.luke.basic.entity.DtoDicCatalog;
import cn.luke.basic.enums.EnumBaseParams;
import cn.luke.basic.mapper.MapperDic;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by Luke on 2025/3/8 17:03.
 */
@Service
@Transactional
public class ServiceDic extends ServiceImpl<MapperDic, DtoDic> implements BaseService<DtoDic>{
    @Override
    public LambdaQueryWrapper<DtoDic> fillParams(Map<String, Object> params) {
        return null;
    }

    @Resource
    private ServiceDicCatalog serviceDicCatalog;

    /**
     * 添加字典
     * @param dic 字典信息
     */
    public synchronized void doAdd(DtoDic dic){
        //检查字典目录是否为内置目录
        DtoDicCatalog catalog = serviceDicCatalog.checkSystem(dic.getCatalogId());
        Assert.state(catalog.getDicCode().equals(dic.getDicCode()), "字典目录编码不合法, 请检查");
        //查询当前目录下已经存在的字典值, 用于在增加时判断字典值是否重复
        LambdaQueryWrapper<DtoDic> qw = loadQw()
                .eq(DtoDic::getDicCode, dic.getDicCode());
        List<DtoDic> hisList = this.list(qw);
        Set<String> hisSet = new HashSet<>();
        if(!CollectionUtils.isEmpty(hisList)){
            hisList.forEach(item->{
                hisSet.add(item.getDicValue());
            });
        }
        //允许一次增加多个值,以","分隔
        String[] values = dic.getDicValue().split(",");
        List<DtoDic> addList = new ArrayList<>();
        String douser = (String) StpUtil.getSession().get(EnumBaseParams.douser.name());
        for (String value : values) {
            if(hisSet.contains(value)){
                continue;
            }
            addList.add(new DtoDic()
                    .setDicCode(dic.getDicCode())
                    .setDicValue(value)
                    .setParamMark(dic.getParamMark())
                    .setPid(dic.getPid())
                    .setShowOrder(dic.getShowOrder())
                    .setStatus(0).setFlagSystem(0).setDouser(douser)
                    .setRemark(dic.getRemark())
            );
        }
        this.saveBatch(addList);
    }

    /**
     * 修改字典值
     * @param dic 字典信息
     */
    public synchronized void doUpdate(DtoDic dic){
        DtoDic tmp = findCheckById(Math.toIntExact(dic.getId()), true);
        //检查字典值是否为系统内置字典值
        Assert.state(tmp.getFlagSystem() == 0, "当前字典值为系统内置, 无法执行编辑操作");
        //清除不能修改的字段
        dic.setDicCode(null).setFlagSystem(null).setStatus(null).setDicValue(null)
                .setDouser(null).setDotime(null).setUptime(null);
        this.updateById(dic);
    }

    /**
     * 变更字典值状态
     * @param id ID
     * @param status 状态
     */
    public synchronized void upStatus(Long id, Integer status){
        DtoDic tmp = findCheckById(Math.toIntExact(id), true);
        //检查字典值是否为系统内置字典值
        Assert.state(tmp.getFlagSystem() == 0, "当前字典值为系统内置, 无法执行启禁用操作");
        Assert.state(!Objects.equals(status, tmp.getStatus()), "当前状态与请求状态一致, 无需重复操作");
        DtoDic dic = new DtoDic().setId(id).setStatus(status);
        this.updateById(dic);
    }

    /**
     * 根据字典目录编码查询字典值
     * @param catalogCode 字典目录编码
     * @return List<DtoDic>
     */
    public Map<String, List<DtoDic>> findByCatalogCode(String catalogCode){
        HashSet<String> catalogSet = new HashSet<>(Arrays.asList(catalogCode.split(",")));
        LambdaQueryWrapper<DtoDic> qw = loadQw();
        if(catalogSet.size() == 1){
            qw.eq(DtoDic::getDicCode, catalogCode);
        }else{
            qw.in(DtoDic::getDicCode, catalogSet);
        }
        qw.orderByAsc(DtoDic::getStatus)
                .orderByDesc(DtoDic::getShowOrder);
        List<DtoDic> list = this.list(qw);
        return list.stream().collect(Collectors.groupingBy(DtoDic::getDicCode));
    }

}
